// app/service/user.js
const Service = require('egg').Service;

class SocialService extends Service {
  // 发布说说
  async publish({
    article,
    pictures = [],
    tags = [],
  }) {
    const row = await this.app.model.transaction(t => this.ctx.model.Article.create({
      article,
      pictures: pictures.join(';'),
      tags: tags.join(';'),
      creatorId: this.ctx.session.user.userid,
    }, {
      transaction: t,
    }));
    return row.dataValues.id;
  }

  // 点赞/消赞
  async like({
    articleId,
  }) {
    const params = {
      articleId,
      creatorId: this.ctx.session.user.userid,
    };
    const { app, ctx } = this;
    const linkLog = await ctx.model.Like.findOne({
      where: params,
    });
    if (linkLog) {
      // 消赞
      await app.model.transaction(t => ctx.model.Like.destroy({
        where: params,
      }, {
        transaction: t,
      }));
    } else {
      // 点赞
      await app.model.transaction(t => ctx.model.Like.create(params, {
        transaction: t,
      }));
    }
    return true;
  }

  // 评论
  async comment({
    articleId,
    comment,
    at,
  }) {
    const { app, ctx } = this;
    await app.model.transaction(t => ctx.model.Comment.create({
      articleId,
      comment,
      at,
      creatorId: ctx.session.user.userid,
    }, {
      transaction: t,
    }));
    return true;
  }
  // 评论
  async queryComments({
    articleId,
    start,
    limit,
  }) {
    const { app, ctx } = this;
    const { rows, count } = await app.model.transaction(t => ctx.model.Comment.findAndCount({
      order: [['id', 'desc']],
      where: {
        articleId,
      },
      limit,
      offset: start,
      include: [{
        model: ctx.model.User,
        as: 'creator',
        attributes: [
          ['id', 'userid'], 'nickname', 'avatar',
        ],
      }],
    }, {
      transaction: t,
    }));
    return {
      list: rows,
      count,
    };
  }

  // 关注 / 取关
  async attention({
    to,
  }) {
    const params = {
      to,
      from: this.ctx.session.user.userid,
    };
    const { app, ctx } = this;
    const linkLog = await ctx.model.Attention.findOne(params);
    if (linkLog) {
      // 取消关注
      await app.model.transaction(t => ctx.model.Attention.destroy(params, {
        transaction: t,
      }));
    } else {
      // 关注
      await app.model.transaction(t => ctx.model.Attention.create(params, {
        transaction: t,
      }));
    }
    return true;
  }

  // 获取文章
  async getArticleList({
    tags = [],
    nickname = '',
    start = 0,
    limit = 10,
  }) {
    const { app, ctx } = this;
    let result;
    const articleQuery = {
      order: [['id', 'desc']],
      where: {},
      limit,
      offset: start,
      include: [
        {
          model: ctx.model.User,
          as: 'creator',
          attributes: [
            ['id', 'userid'], 'nickname', 'avatar',
          ],
        },
        {
          model: ctx.model.Comment,
          attributes: ['id'],
        },
      ],
    };
    if (tags.length > 0) {
      // 搜索标签
      articleQuery.where = {
        tags: {
          [app.Sequelize.Op.like]: `%${tags.join('%')}%`,
        },
      };
      result = await ctx.model.Article.findAndCount(articleQuery);
    } else if (nickname) {
      const user = await ctx.model.User.findOne({
        where: {
          nickname,
        },
        attributes: ['id'],
      });
      if (user) {
        articleQuery.where = {
          creatorId: user.id,
        };
        result = await ctx.model.Article.findAndCount(articleQuery);
      } else {
        result = { rows: [], count: 0 };
      }
    } else {
      result = await ctx.model.Article.findAndCount(articleQuery);
    }

    const { rows, count } = result;
    const list = rows.map(({ dataValues }) => dataValues);
    const likes = await this.likeCount(list.map(item => item.id));
    return {
      list: list.map(item => ({
        ...item,
        pictures: item.pictures.split(';').filter(v => !!v),
        tags: item.tags.split(';').filter(v => !!v),
        likeCount: likes[item.id].count,
        like: likes[item.id].like,
        comments: item.comments.length,
      })),
      count,
    };
  }

  async articleDetail({
    id,
  }) {
    const { ctx } = this;
    const article = await ctx.model.Article.findOne({
      where: {
        id,
      },
      include: [{
        model: ctx.model.User,
        as: 'creator',
        attributes: [
          ['id', 'userid'], 'nickname', 'avatar',
        ],
      }],
    });
    const likes = await this.likeCount([article.id]);
    return {
      ...article.dataValues,
      pictures: article.pictures.split(';').filter(v => !!v),
      tags: article.tags.split(';').filter(v => !!v),
      likeCount: likes[article.id].count,
      like: likes[article.id].like,
    };
  }

  async likeCount(articleList = []) {
    const ctx = this.ctx;
    // like
    const result = await ctx.model.Like.findAll({
      where: {
        articleId: articleList,
      },
    });
    const articleMap = articleList.reduce((acc, next) => { acc[next] = { count: 0, like: false }; return acc; }, {});
    return result
      .map(({ dataValues }) => dataValues)
      .reduce((acc, next) => {
        acc[next.articleId] = {
          count: acc[next.articleId].count + 1,
          like: acc[next.articleId].like || ctx.session.user.userid === next.creatorId,
        };
        return acc;
      }, articleMap);
  }
}

module.exports = SocialService;
